home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Mania 6
/
MacMania 6.toast
/
/
Multimedia & Desktop
/
VideoToolbox
/
VideoToolboxSources
/
NoiseFill.c
< prev
next >
Wrap
Text File
|
1995-05-27
|
7KB
|
168 lines
/* NoiseFill.c
© 1989-1994 Denis G. Pelli.
error=NoiseFill(window,&rect,dx,dy,randomPhase);
Fills the rect in the window with noise. The noise is made up of black & white
checks, each dx pixels wide by dy pixels high. Random phase is optional. (dx and
dy are doubles, and need not be integral. The noise is synthesized with 1-pixel
checks and expanded by CopyBits, which is capable of expansion by non-integral
amounts.)
error=NoiseFillBits(pixmapPtr,&rect,dx,dy,randomPhase);
Same, but accepts a pix/bitmap ptr in place of the window.
error=MakeNoise1(dx,dy,randomPhase,pixmapPtr);
Same, but fills the whole pix/bitmap, i.e. uses pixmapPtr->bounds as the rect.
Obsolete, retained solely for compatibility.
We use the current port's ForeColor and BackColor to make the noise. (If
baseAddr==NULL, we share the color table of the current device.) Apple's
GetGWorld and SetGWorld calls are a convenient way of getting, changing, and
restoring the current port and device.
If pixmapPtr->baseAddr==NULL then the data area will be allocated for you. You
must set pixmapPtr->bounds and pixmapPtr->pixelSize; the rest of the PixMap
struct will be filled in by NoiseFillBits. It will install a handle to the
current device's color table. The values filled into the fields are necessarily
somewhat arbitrary. For more control, fill in the fields yourself, using
NewPixMap(), and allocate the data area yourself before calling NoiseFillBits().
HISTORY:
6/21/89 dgp changed frameBytes and bufferBytes to long so that this code won't crash
if the pixelSize is greater than 1 bit.
8/5/89 dgp wrote and installed randU(), which yields two random bytes per call, instead
of rand() which yields only one, allowing the noise generation to go twice
as fast.
3/11/90 dgp Changed dx and dy from int to double. This allows nonuniform cell size,
which arises when CopyBits expands by these nonintegral factors. Results
will be same as before when integral values are supplied.
Made the cosmetic change of replacing "unsigned long" by "size_t".
3/20/90 dgp make compatible with MPW C.
3/31/90 dgp set pmVersion to zero for compatibility with QD32
8/7/90 dgp Now uses the current ForeColor and BackColor to make the noise.
For future compatibility, now zeroes the packType, etc. fields.
10/1/90 dgp Cosmetic changes: replaced two OffsetRect calls by CenterRectInRect call.
11/16/90 dgp Added RANDOM_PHASE.
4/20/91 dgp Added new MakeNoise1() that accepts a single PixMap, and allocates
its data area only if baseAddr==NULL, otherwise assuming that it already
exists. I rewrote MakeNoise() to simply call MakeNoise1() repeatedly.
MakeNoise() now seems obsolete, but is retained for compatibility with old
programs.
4/24/91 dgp Fixed bug introduced into MakeNoise() on 4/20, which resulted in all the
PixMaps using the same buffer.
8/6/91 dgp Replaced use of randU() by RandFill(), which is twice as fast.
8/24/91 dgp Made compatible with THINK C 5.0.
4/17/92 dgp Removed hidden assumption that bits->bounds.top and bits->bounds.left
were both zero. If they were negative MakeNoise1 would allocate too
little space, and then overwrite memory and crash.
4/27/92 dgp Initialize all remaining fields of the *bits PixMap, and copy the current
device's color table handle.
10/22/92 dgp Check for error in CopyBits.
9/5/94 dgp removed assumption in printf's that int==short.
11/21/94 dgp in response to note from Marty Wachter, improve centering algorithm, so
that if dx & dy are integral the final image is made of whole checks.
11/21/94 dgp renamed NoiseFill.c and added new calling interfaces, analogous to those
for CopyWindows and CopyBits.
*/
#include "VideoToolbox.h"
int MakeNoise1(double dx,double dy,Boolean randomPhase,PixMap *bits)
{
return NoiseFillBits(bits,&bits->bounds,dx,dy,randomPhase);
}
int NoiseFill(CWindowPtr window,Rect *r,double dx,double dy,Boolean randomPhase)
{
Boolean error,ok;
if(IsGWorldPtr(window)){
ok=LockPixels(window->portPixMap);
if(!ok)return 2;
}
if(IsGrafPtr(window))
error=NoiseFillBits((PixMap *)&((WindowPtr)window)->portBits,r,dx,dy,randomPhase);
else{
HLock((Handle)window->portPixMap);
error=NoiseFillBits(*window->portPixMap,r,dx,dy,randomPhase);
HUnlock((Handle)window->portPixMap);
}
if(IsGWorldPtr(window))UnlockPixels(window->portPixMap);
return error;
}
int NoiseFillBits(PixMap *bits,Rect *r,double dx,double dy,Boolean randomPhase)
{
BitMap buffer,bigBuffer;
Rect srcRect;
size_t frameBytes,bufferBytes;
static const RGBColor blackRGB={0,0,0},whiteRGB={0xffff,0xffff,0xffff};
RGBColor backRGB,foreRGB;
int error;
if(dx<=0 || dy<=0)return 3;
srandU((unsigned int)rand()); /* seed our unsigned random number generator */
GetBackColor(&backRGB);
GetForeColor(&foreRGB);
/* allocate buffer BitMap */
SetRect(&buffer.bounds,0,0,ceil((r->right - r->left)/dx),ceil((r->bottom - r->top)/dy));
if(randomPhase){
buffer.bounds.right++;
buffer.bounds.bottom++;
}
buffer.rowBytes=(buffer.bounds.right + 31 & ~31)/8; /* round up to multiple of 32 bits */
bufferBytes=(size_t) buffer.rowBytes * (size_t) buffer.bounds.bottom;
buffer.baseAddr=(Ptr) NewPtr(bufferBytes);
if(buffer.baseAddr == NULL)return 4;
/* allocate bigBuffer BitMap */
SetRect (&bigBuffer.bounds,0,0,(int)round(buffer.bounds.right*dx),
(int)round(buffer.bounds.bottom*dy));
bigBuffer.rowBytes=(bigBuffer.bounds.right + 31 & ~31)/8; /* round up to multiple of 32 bits */
bigBuffer.baseAddr=(Ptr) NewPtr((size_t) bigBuffer.rowBytes * (size_t) bigBuffer.bounds.bottom);
if(bigBuffer.baseAddr == NULL){
DisposePtr(buffer.baseAddr);
return 5;
}
/* if necessary, fill in pixmap's fields and allocate its data area */
if(bits->baseAddr == NULL){
// If we're allocating, assume *bits is a PixMap, not a Bitmap.
bits->hRes=bits->vRes=0x480000; // 72 dpi
bits->pmVersion=bits->packType=bits->packSize=0;
bits->planeBytes=bits->pmReserved=0;
bits->cmpCount=1;
bits->cmpSize=bits->pixelSize;
bits->pmTable=(**(**GetGDevice()).gdPMap).pmTable;
bits->rowBytes=((bits->bounds.right-bits->bounds.left)*bits->pixelSize + 31 & ~31)/8; /* round up to multiple of 32 bits */
frameBytes=(size_t) bits->rowBytes * (bits->bounds.bottom-bits->bounds.top);
bits->rowBytes |= 0x8000; /* mark it as a PixMap */
bits->baseAddr=(char *) NewPtr(frameBytes);
if(bits->baseAddr == NULL)return 6;
}
if((size_t)bits->baseAddr%4 != 0L){
printf("WARNING: Frame buffer address is not long aligned. %s\007\n",__FILE__);
}
/* create random noise */
/* First create a random bit image, all bits uncorrelated. */
RandFill(buffer.baseAddr,bufferBytes);
/* Now expand image so that each random bit becomes a dx by dy rectangle. */
RGBBackColor(&whiteRGB);
RGBForeColor(&blackRGB);
CopyBits(&buffer,&bigBuffer,&buffer.bounds,&bigBuffer.bounds,srcCopy,NULL);
error=QDError();
if(error)printf("MakeNoise1:a: CopyBits error %d\n",error);
/* Finally copy it into the bit/pixmap, trimming it down to the correct size. */
RGBBackColor(&backRGB);
RGBForeColor(&foreRGB);
srcRect=*r;
OffsetRect(&srcRect,-srcRect.left,-srcRect.top);
if(randomPhase) OffsetRect(&srcRect,nrand(dx),nrand(dy));
else CenterRectInRect(&srcRect,&bigBuffer.bounds);
CopyBits(&bigBuffer,(BitMap *)bits,&srcRect,r,srcCopy,NULL);
error=QDError();
DisposPtr((void *) buffer.baseAddr);
DisposPtr((void *) bigBuffer.baseAddr);
return error;
}